/**
* This file is part of mobileworks.
*
* mobileworks is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* You should have received a copy of the GNU General Public License
* along with dev.clipall.  If not, see <http://www.gnu.org/licenses/>.
*
* https://code.google.com/p/mobileworks/
*/

package base;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import javax.microedition.lcdui.Image;
import javax.microedition.midlet.MIDlet;
import view.font.Font;
import view.font.FontFactory;

/**
 *
 * @author Erol Hira
 */
public class ResourceLoader {
    
    private MIDlet midlet;
    
    private static ResourceLoader loader;
    
    private ResourceLoader(){        
    }
    
    public static ResourceLoader getInstance(MIDlet midlet){
        if(loader == null){
            loader = new ResourceLoader();
            loader.midlet = midlet;
        }
        return loader;
    }
    
    public void load() throws Exception{
        setupDevice();
        loadFonts();
        loadSkeleton();
    }
    
    private void setupDevice(){        
        String deviceId = midlet.getAppProperty("Device-Id");
        System.out.println("device id : " + deviceId);
        Settings.setDeviceSpecificProperties(Byte.parseByte(deviceId));
    }
    
    private void loadFonts() throws Exception {
        
        DataInputStream in = 
                        new DataInputStream(
                            getClass().getResourceAsStream("/fonts.dat"));
        
        byte fontCnt = in.readByte();
        
        Font[] fonts = new Font[fontCnt];
        
        // read font names
        String[] fontNames = new String[fontCnt];
        for(int i = 0; i < fontCnt; i++){            
            fontNames[i] = in.readUTF();
        }
        
        // read font widths and chars
        for(int i = 0; i < fontCnt; i++){
            
            byte charCnt = in.readByte();
            int[] widths = new int[charCnt];
            char[] chars = new char[charCnt];
            
            for(int j = 0; j < charCnt; j++){
                widths[j] = in.readByte();
            }
            
            for(int j = 0; j < charCnt; j++){
                chars[j] = in.readChar();
            }
            
            Font font = new Font(
                            Image.createImage("/" + fontNames[i] + ".png"),
                            chars, widths, -3);
            fonts[i] = font;
        }
        
        FontFactory.fonts = fonts;
    }
    
    private void loadSkeleton() throws Exception{
        
        DataInputStream in = 
                        new DataInputStream(
                            getClass().getResourceAsStream("/pack.dat"));
        
        // read props
        int byteCnt = in.readInt();        
        byte[] bytes = new byte[byteCnt];
        in.read(bytes);
        ResourceAccess.propArr = parseBytesToDoubleShorts(bytes);                
        
        // read commandArr
        byteCnt = in.readInt();        
        bytes = new byte[byteCnt];
        in.read(bytes);
        ResourceAccess.commandArr = parseBytesToDoubleShorts(bytes);                                                
        
        // read transArr
        byteCnt = in.readInt();        
        bytes = new byte[byteCnt];
        in.read(bytes);
        ResourceAccess.transArr = parseBytesToDoubleShorts(bytes);          
        
        // read actionArr
        byteCnt = in.readInt();
        bytes = new byte[byteCnt];
        in.read(bytes);
        ResourceAccess.actionArr = parseBytesToDoubleShorts(bytes);                
        
        // read funcArr
        byteCnt = in.readInt();
        bytes = new byte[byteCnt];
        in.read(bytes);
        ResourceAccess.funcArr = parseBytesToDoubleStrings(bytes);
        
        // read styles
        byteCnt = in.readInt();
        bytes = new byte[byteCnt];
        in.read(bytes);
        ResourceAccess.styles = parseBytesToDoubleShorts(bytes);
        
        // read states
        byteCnt = in.readInt();
        bytes = new byte[byteCnt];
        in.read(bytes);
        ResourceAccess.states = parseBytesToTripleShorts(bytes);
        
        // read pages
        byteCnt = in.readInt();
        bytes = new byte[byteCnt];
        in.read(bytes);
        ResourceAccess.pages = parseBytesToQuadShorts(bytes);
        
        // read nonNumericPropValuesArr
        byteCnt = in.readInt();
        bytes = new byte[byteCnt];
        in.read(bytes);
        ResourceAccess.nonNumericPropValuesArr = parseBytesToStrings(bytes);
        
        System.out.println("skeleton loaded");
    }
    
    private String[] parseBytesToStrings(byte[] bytes) throws Exception{
    
        DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
        
        String[] strs;
        
        short l1Cnt = in.readShort();
        strs = new String[l1Cnt];
        
        for(int i = 0; i < l1Cnt; i++){
            
            strs[i] = in.readUTF();
        }
        
        return strs;
    }
    
    private String[][] parseBytesToDoubleStrings(byte[] bytes) throws Exception{
    
        DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
        
        String[][] strs;
        
        short l1Cnt = in.readShort();
        strs = new String[l1Cnt][];
        
        for(int i = 0; i < l1Cnt; i++){
            
            short l2Cnt = in.readShort();
            strs[i] = new String[l2Cnt];
            
            for(int j = 0; j < l2Cnt; j++){
                
                strs[i][j] = in.readUTF();
            }
        }
        
        return strs;
    }
    
    private short[][] parseBytesToDoubleShorts(byte[] bytes) throws Exception{
        
        DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
        
        short[][] shorts;
        
        short l1Cnt = in.readShort();        
        shorts = new short[l1Cnt][];
        
        for(int i = 0; i < l1Cnt; i++){
            
            short l2Cnt = in.readShort();            
            shorts[i] = new short[l2Cnt];
            
            for(int j = 0; j < l2Cnt; j++){
                
                shorts[i][j] = in.readShort();
            }            
        }
        
        return shorts;
    }
    
    private short[][][] parseBytesToTripleShorts(byte[] bytes) throws Exception{
        
        DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
        
        short[][][] shorts;
        
        short l1Cnt = in.readShort();
        shorts = new short[l1Cnt][][];
        
        for(int i = 0; i < l1Cnt; i++){
            
            short l2Cnt = in.readShort();
            shorts[i] = new short[l2Cnt][];
            
            for(int j = 0; j < l2Cnt; j++){
                
                short l3Cnt = in.readShort();
                shorts[i][j] = new short[l3Cnt];
                
                for(int k = 0; k < l3Cnt; k++){
                    
                    shorts[i][j][k] = in.readShort();
                }
            }            
        }
        
        return shorts;
    }
    
    private short[][][][] parseBytesToQuadShorts(byte[] bytes) throws Exception{
        
        DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));
        
        short[][][][] shorts;
        
        short l1Cnt = in.readShort();
        shorts = new short[l1Cnt][][][];
        
        for(int i = 0; i < l1Cnt; i++){
            
            short l2Cnt = in.readShort();
            shorts[i] = new short[l2Cnt][][];
            
            for(int j = 0; j < l2Cnt; j++){
                
                short l3Cnt = in.readShort();
                shorts[i][j] = new short[l3Cnt][];
                
                for(int k = 0; k < l3Cnt; k++){
                    
                    short l4Cnt = in.readShort();
                    shorts[i][j][k] = new short[l4Cnt];
                    
                    for(int m = 0; m < l4Cnt; m++){
                    
                        shorts[i][j][k][m] = in.readShort();
                    }
                }
            }            
        }
        
        return shorts;
    }
}
